import json

from re_common.baselibrary.tools.all_requests.mrequest import MRequest
from re_common.baselibrary.utils.core.requests_core import INSIDE_HEADERS, MsgCode

from apps.core.global_model import InputPlatformModel
from apps.crawler_platform.core_api.models import SaveMongoModel, SelectMongoModel, ResetMongoModel
from apps.crawler_platform.core_platform.core_g import IsHasEnum
from apps.crawler_platform.util.requestapihelper import RequestApiHelper
from settings import URLDISTRIBUTED


class NoSqlUtil(object):

    @classmethod
    def set_is_his(cls, pm, is_his: str):
        """
        判断本次下载是否完成，如果完成，将在mongo表中当作一次历史记录
        is_his: True or False
        :return:
        """
        pm.set_is_his(is_his)

    @classmethod
    def set_save_para(cls, pm):
        """
        通用保存模型
        """
        return InputPlatformModel(
            data=SaveMongoModel(
                id=pm.Id,
                table=pm.one_para.task_set.nosql_table,
                is_his=str(pm.get_is_his(state=IsHasEnum.LATEST)),
                his_cnt=pm.one_para.task_set.history_cnt,
                para=pm.para,
                data=pm.down_model.dict()
            )).json()

    @classmethod
    def set_save_para_etl(cls, pm):
        """
        etl保存模型
        """
        meta = InputPlatformModel(
            data=SaveMongoModel(
                table=pm.table,
                data=pm.deal_model.save_data
            )).json()
        tmp_extra = pm.deal_model.extra_meta
        extra_meta = {}
        if len(tmp_extra) > 0:
            for k, v in tmp_extra.items():
                extra_meta[k] = InputPlatformModel(
                    data=SaveMongoModel(
                        table="journal_latest",
                        data=v
                    )).json()
        ref = None
        ref_data = pm.deal_model.ref_data
        if ref_data != None and len(ref_data) > 0:
            ref = InputPlatformModel(
                data=SaveMongoModel(
                    table="journal_ref_latest",
                    data=ref_data
                )).json()
        return meta, ref, extra_meta

    @classmethod
    def set_save_parse_etl(cls, pm):
        """
        etl保存模型
        """
        save_data = pm.deal_model.save_data
        meta_list = list()
        for data in save_data:
            meta = InputPlatformModel(
                data=SaveMongoModel(
                    table=data['table'],
                    data=data['data']
                )).json()
            meta_list.append(meta)
        return meta_list

    @classmethod
    def set_save_para_etl_validate_error(cls, pm):
        """
        etl保存模型
        """
        data = InputPlatformModel(
            data=SaveMongoModel(
                table="validate_error_latest",
                data=pm.data
            )).json()
        return data

    @classmethod
    def set_save_para_etl_suc_logs(cls, pm):
        """
        etl成功日志保存模型
        """
        data = InputPlatformModel(
            data=SaveMongoModel(
                table="etl_suc_logs",
                data=pm.data
            )).json()
        return data

    @classmethod
    def set_select_para(cls, pm):
        """
        通用获取模型
        """
        id_ = "_".join([str(pm.para[tmp]) for tmp in pm.one_para.task_set.get_id_list()])
        # 查询mongoapi需要的请求参数结构
        field = {"new_data": 1}
        if hasattr(pm, "field"):
            field = pm.field
        table = pm.one_para.task_set.nosql_table
        data = InputPlatformModel(
            data=SelectMongoModel(
                # 只查询 new_data； {"new_data": 1} 属于mongo语法
                field=field,
                table=table,
                and_param={"_id": id_},
            )).json()
        return data

    @classmethod
    def set_select_para_latest(cls, pm):
        """
        通用获取latest查询模型
        """
        and_param = pm.and_param
        table = pm.table
        # 查询mongoapi需要的请求参数结构
        field = {}
        data = InputPlatformModel(
            data=SelectMongoModel(
                field=field,
                table=table,
                and_param=and_param,
                limit=pm.limit
            )).json()
        return data

    @classmethod
    def set_reset_new_data(cls, pm):
        """
        通用获取模型
        """
        id_ = "_".join([pm.para[tmp] for tmp in pm.one_para.task_set.get_id_list()])
        # 查询mongoapi需要的请求参数结构
        data = InputPlatformModel(
            data=ResetMongoModel(
                id=id_,
                table=pm.one_para.task_set.nosql_table,
            )).json()
        return data

    @classmethod
    async def save_nosql_html(cls, pm):
        """
        请求保存api
        :param pm:
        :return:
        """
        data = cls.set_save_para(pm)
        url = await URLDISTRIBUTED.get_mongo_save_url()
        rrq = RequestApiHelper.get_rrq()
        kwargs = {
            "rrq": rrq,
            "header": INSIDE_HEADERS,
            "url": url,
            "timeout": 30,
            "data": data,
            "moths": MRequest.POST,
            "middler_list": [rrq.status_code_middlerwares,
                             rrq.is_none_html_middlerwares,
                             rrq.is_null_html_middlerwares,
                             rrq.msg_status_code_middlerwares]
        }
        bools, dicts = await RequestApiHelper.mongo_save(**kwargs)
        return bools, dicts

    @classmethod
    async def save_nosql_html_etl(cls, pm):
        """
        etl请求保存api
        :param pm:
        :return:
        """
        bools, dicts = False, {"msg_code": MsgCode.MONGO_ERROR}
        meta_list = cls.set_save_parse_etl(pm)
        # 如果没有要保存到latest的数据 就返回true,比如bookan图片全文
        if meta_list == []:
            return True, {}
        for meta in meta_list:
            url = await URLDISTRIBUTED.get_mongo_save_etl_url()
            rrq = RequestApiHelper.get_rrq()
            kwargs = {
                "rrq": rrq,
                "header": INSIDE_HEADERS,
                "url": url,
                "timeout": 30,
                "data": meta,
                "moths": MRequest.POST,
                "middler_list": [rrq.status_code_middlerwares, rrq.is_none_html_middlerwares,
                                 rrq.is_null_html_middlerwares,
                                 rrq.msg_status_code_middlerwares]
            }
            bools, dicts = await RequestApiHelper.mongo_save(**kwargs)
            if not bools:
                break
        return bools, dicts

    @classmethod
    async def read_nosql_html(cls, pm):
        """
        按条件查询nosql数据库
        """
        # 期刊列表级默认保存历史
        data = cls.set_select_para(pm)
        url = await URLDISTRIBUTED.get_select_url()
        rrq = RequestApiHelper.get_rrq()
        kwargs = {
            "rrq": rrq,
            "header": INSIDE_HEADERS,
            "url": url,
            "timeout": 30,
            "data": data,
            "moths": MRequest.POST,
            "middler_list": [rrq.status_code_middlerwares, rrq.is_none_html_middlerwares, rrq.is_null_html_middlerwares,
                             rrq.msg_status_code_middlerwares]
        }
        bools, dicts = await RequestApiHelper.mongo_save(**kwargs)
        if bools:
            pm.mongo_html = json.loads(rrq.html)
        return bools, dicts

    @classmethod
    async def read_nosql_latest(cls, pm):
        """
        按条件查询nosql数据库latest
        """
        # 期刊列表级默认保存历史
        data = cls.set_select_para_latest(pm)
        url = await URLDISTRIBUTED.get_select_url()
        rrq = RequestApiHelper.get_rrq()
        kwargs = {
            "rrq": rrq,
            "header": INSIDE_HEADERS,
            "url": url,
            "timeout": 30,
            "data": data,
            "moths": MRequest.POST,
            "middler_list": [rrq.status_code_middlerwares, rrq.is_none_html_middlerwares, rrq.is_null_html_middlerwares,
                             rrq.msg_status_code_middlerwares]
        }
        bools, dicts = await RequestApiHelper.mongo_save(**kwargs)
        if bools:
            pm.mongo_html = json.loads(rrq.html)
        return bools, dicts

    @classmethod
    async def reset_new_data(cls, pm):
        """
        按条件查询nosql数据库
        """
        # 期刊列表级默认保存历史
        data = cls.set_reset_new_data(pm)
        url = await URLDISTRIBUTED.get_reset_new_data_url()
        rrq = RequestApiHelper.get_rrq()
        kwargs = {
            "rrq": rrq,
            "header": INSIDE_HEADERS,
            "url": url,
            "timeout": 30,
            "data": data,
            "moths": MRequest.POST,
            "middler_list": [rrq.status_code_middlerwares, rrq.is_none_html_middlerwares, rrq.is_null_html_middlerwares,
                             rrq.msg_status_code_middlerwares]
        }
        bools, dicts = await RequestApiHelper.mongo_save(**kwargs)
        return bools, dicts

    @classmethod
    async def save_nosql_html_etl_validate_error(cls, pm):
        """
        etl请求保存api
        :param pm:
        :return:
        """
        data = cls.set_save_para_etl_validate_error(pm)
        url = await URLDISTRIBUTED.get_mongo_save_etl_url()
        rrq = RequestApiHelper.get_rrq()
        kwargs = {
            "rrq": rrq,
            "header": INSIDE_HEADERS,
            "url": url,
            "timeout": 30,
            "data": data,
            "moths": MRequest.POST,
            "middler_list": [rrq.status_code_middlerwares, rrq.is_none_html_middlerwares, rrq.is_null_html_middlerwares,
                             rrq.msg_status_code_middlerwares]
        }
        bools, dicts = await RequestApiHelper.mongo_save(**kwargs)
        return bools, dicts

    @classmethod
    async def save_nosql_etl_suc_logs(cls, pm):
        """
        etl请求保存capi
        :param pm:
        :return:
        """
        data = cls.set_save_para_etl_suc_logs(pm)
        url = await URLDISTRIBUTED.get_mongo_save_etl_url()
        rrq = RequestApiHelper.get_rrq()
        kwargs = {
            "rrq": rrq,
            "header": INSIDE_HEADERS,
            "url": url,
            "timeout": 30,
            "data": data,
            "moths": MRequest.POST,
            "middler_list": [rrq.status_code_middlerwares, rrq.is_none_html_middlerwares, rrq.is_null_html_middlerwares,
                             rrq.msg_status_code_middlerwares]
        }
        bools, dicts = await RequestApiHelper.mongo_save(**kwargs)
        return bools, dicts
